package com.xnx.bincker.leader.controller.admin.system;

import com.xnx.bincker.leader.core.annotation.Authority;
import com.xnx.bincker.leader.core.annotation.IgnoreProperties;
import com.xnx.bincker.leader.core.annotation.Menu;
import com.xnx.bincker.leader.core.domain.BasicEntity;
import com.xnx.bincker.leader.core.security.SecurityUserHolder;
import com.xnx.bincker.leader.domain.User;
import com.xnx.bincker.leader.exception.data.ValidationException;
import com.xnx.bincker.leader.exception.data.datasource.DataNotExistsException;
import com.xnx.bincker.leader.exception.permission.PermissionDeniedException;
import com.xnx.bincker.leader.service.UserService;
import com.xnx.bincker.leader.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 用户管理
 */
@RestController
@RequestMapping("/admin/system/user")
public class UserController {
	private final UserService userService;

	@Autowired
	public UserController(
	        UserService userService
            ) {
		this.userService = userService;
	}

    /**
     * 用户列表
     * @param user 查询参数
     * @param page 分页
     * @param size 分页大小
     * @param sort 排序
     */
    @GetMapping
	@Menu(id="ff93b2a9-ae4a-40cf-9a35-a6e7a5434516", name = "用户管理")
	@Authority(id="67e27575-0db8-4b21-ad6e-43e48d906379", remark = "用户列表")
    @IgnoreProperties(target = User.class, value = {"password"})
	public Page<User> list(
	        @Validated(BasicEntity.ValidGroup.Search.class) User user,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size,
            Sort sort
    ){
        PageRequest pageRequest = PageRequest.of(page, size, sort==null?Sort.unsorted():sort);
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                .withIgnorePaths("id", "password");
        return userService.findAll(Example.of(user, matcher), pageRequest);
	}

	@GetMapping(value = "/{id}")
    @Authority(id="3fdb4f28-0c61-4272-b49d-4de7f4ab9959", remark = "用户详情")
    @IgnoreProperties(target = User.class, value = {"password"})
	public User get(@PathVariable String id){
        return userService.findById(id).orElse(new User());
	}

	@PostMapping
    @Authority(id="0b112050-763c-4e5d-b4cd-decde3cb34c6", remark = "新增用户")
    @IgnoreProperties(target = User.class, value = {"password"})
	public User add(@RequestBody @Validated(BasicEntity.ValidGroup.Insert.class) User user) {
	    checkPermission(user);
        User example = new User();
        example.setUsername(user.getUsername());
        if (userService.count(Example.of(example)) > 0) {
            FieldError fieldError = new FieldError("user", "username", "用户名已存在");
            throw new ValidationException(Collections.singletonList(fieldError));
        }
        if (StringUtils.hasLength(user.getPhoneNumber())) {
            example.setUsername(null);
            example.setPhoneNumber(user.getPhoneNumber());
            if (userService.count(Example.of(example)) > 0) {
                FieldError fieldError = new FieldError("user", "phoneNumber", "手机号已被注册");
                throw new ValidationException(Collections.singletonList(fieldError));
            }
        }
        return userService.save((User) user.cloneByAnnotation(BasicEntity.Insert.class));
    }

    @PutMapping(value = "/{id}")
    @Authority(id="6332e0d8-ee8c-4a1b-84d2-a380757cf712", remark = "编辑用户")
    @IgnoreProperties(target = User.class, value = {"password"})
    public User update(@PathVariable String id, @RequestBody @Validated(BasicEntity.ValidGroup.Update.class) User user) {
        Optional<User> targetOptional = userService.findById(id);
        if(!targetOptional.isPresent()) throw new DataNotExistsException();
        User target = targetOptional.get();
        target.copyProperties(BasicEntity.Update.class, user);
	    checkPermission(target);
	    return userService.save(target);
    }

    @DeleteMapping("/{id}")
    @Authority(id="e7d137fe-d323-45dc-9f4b-459749f947d6", remark = "删除用户")
    public void delete(@PathVariable String id) {
        User user = new User();
        user.setId(id);
        checkPermission(user);
        userService.delete(user);
    }

    /**
     * 检测当前用户是否有更改该用户的权限
     * @param user User 检测的用户
     */
    private void checkPermission(User user){
        User currentUser = SecurityUserHolder.currentUser();
        if (user.hasRule("super_admin")) {
            if (!currentUser.getId().equals(user.getId())) {
                throw new PermissionDeniedException(
                        "超级管理员篡改被截止: 篡改人=" + currentUser.getId() + "\t被篡改人=" + user.getId());
            }
        }
    }
}
